<!DOCTYPE HTML>
<html>

<head><meta name="generator" content="Hexo 3.9.0">
  <meta charset="utf-8">
  
  <title>Elasticsearch.Nest 教程系列 9-4 转换：Field inference | 字段推断 | DeepThought</title>
  <meta name="google-site-verification" content="Ei6mmDdf-cJwox1RvJOeX8Dc720fqWjZQu-Ww2BjBt4">
  
  <meta name="author" content="积慕">
  
  <meta name="description" content="Nest 7 教程,Nest7.x 教程,Elasticsearch.Nest,Elasticsearch.Nest 入门, NEST 入门,NEST上手, Nest 官方文档, NEST 翻译,Elasticsearch.Nest 中文,Elasticsearch.Nest 中文文档, Nest 中文文档,NET ElasticSearch,NET es,NEST 教程, Elasticsearch 客户端,Elasticsearch 7,Elasticsearch 7.x,NEST 7,NEST 7.x,releationName,Field inference,字段推断">
  
  
  <meta name="keywords" content="Nest 7 教程,Nest7.x 教程,Elasticsearch.Nest,Elasticsearch.Nest 入门, NEST 入门,NEST上手, Nest 官方文档, NEST 翻译,Elasticsearch.Nest 中文,Elasticsearch.Nest 中文文档, Nest 中文文档,NET ElasticSearch,NET es,NEST 教程, Elasticsearch 客户端,Elasticsearch 7,Elasticsearch 7.x,NEST 7,NEST 7.x,Field inference,字段推断">
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">

  
  <meta property="og:title" content="Elasticsearch.Nest 教程系列 9-4 转换：Field inference | 字段推断">
  <meta property="og:site_name" content="DeepThought">

  
  <meta property="og:image" content>
  

  <link href="https://pic.zhuliang.ltd/favicon.ico" rel="shortcut icon" type="image/x-icon">
  <link rel="alternate" href="/atom.xml" title="DeepThought" type="application/atom+xml">
  <link rel="stylesheet" href="/css/style.css" media="screen" type="text/css">

  <link rel="stylesheet" href="//at.alicdn.com/t/font_1187293_8fec2ou5fyx.css">

  <!-- <link rel="stylesheet" href="//cdn.bootcss.com/highlight.js/9.6.0/styles/github.min.css"> -->
  <!-- <script src="//cdn.bootcss.com/highlight.js/9.6.0/highlight.min.js"></script> -->
  <script src="/js/highlight.min.js"></script>

  <link rel="stylesheet" href="/css/markdown.css">

  <script src="/js/av-min.3.0.4.js"></script>
  <script src="/js/Valine.min.1.3.6.js"></script>

</head></html>

<body>
  <header id="header" class="inner"><div class="alignleft">
  <h1><a href="/">DeepThought</a></h1>
  <h2><a href="/">知识需沉淀，更需分享</a></h2>
</div>
<nav id="main-nav" class="alignright">
  <ul>
    
      <li><a href="/">首页</a></li>
    
      <li><a href="/about">关于我</a></li>
    
      <li><a href="/atom.xml">订阅RSS</a></li>
    
  </ul>
  <div class="clearfix"></div>
</nav>
<div class="clearfix"></div>
        </header>
  <div id="content" class="inner">
    <div id="main-col" class="alignleft"><div id="wrapper"><article class="post">
  
  <div class="post-content">
    <header>
      
        <div class="icon"></div>
      

 
      
  
    <h1 class="title">Elasticsearch.Nest 教程系列 9-4 转换：Field inference | 字段推断</h1>
  


      
        <time datetime="2020-01-22T08:44:01.000Z">
          create: 2020-01-22 16:44:01 | update: 2020-01-23 12:15:44
            <span style="float: right;">
    <span class="post-count" id="busuanzi_container_page_pv" style="display: inline;">
        
        本文总阅读量: <span id="busuanzi_value_page_pv"></span>&nbsp;次
        <span class="blueSeparate">&nbsp;|&nbsp;</span>
        
        <span class="post-count">文章总字数:&nbsp;2.8k&nbsp;字</span>
    <span class="blueSeparate">&nbsp;|&nbsp;</span>
    <span class="post-count">阅读约需:&nbsp;14&nbsp;分钟</span>
    <br>
</span>
</span>
        </time>
      
            
    </header>
    <div class="entry">
      
      <blockquote>
<ul>
<li>本系列博文是“伪”官方文档翻译（更加本土化），并非完全将官方文档进行翻译，而是在查阅、测试原始文档并转换为自己真知灼见后的“准”翻译。有不同见解 / 说明不周的地方，还请海涵、不吝拍砖 ：）</li>
<li>官方文档见此：<a href="https://www.elastic.co/guide/en/elasticsearch/client/net-api/current/introduction.html" target="_blank" rel="noopener">https://www.elastic.co/guide/en/elasticsearch/client/net-api/current/introduction.html</a></li>
<li>本系列对应的版本环境：<a href="mailto:ElasticSearch@7.3.1" target="_blank" rel="noopener">ElasticSearch@7.3.1</a>，<a href="mailto:NEST@7.3.1" target="_blank" rel="noopener">NEST@7.3.1</a>，IDE 和开发平台默认为 VS2019，.NET CORE 2.1</li>
</ul>
</blockquote>
<hr>
<p>不少 Elasticsearch API 接口在使用的时候会希望知道字段在原始文档中的路径（以字符串的形式），NEST 提供了 Field 类来允许你获得这些字段路径字符串。</p>
<h1 id="构造函数"><a href="#构造函数" class="headerlink" title="构造函数"></a>构造函数</h1><p>通过使用 Field 的构造函数：</p>
<p></p><p class="code-caption" data-lang="csharp" data-line_number="backend" data-trim_indent="backend" data-label_position="outer" data-labels_left="Code" data-labels_right=":" data-labels_copy="Copy Code"><span class="code-caption-label"></span></p><p></p>
<pre><code class="csharp">var fieldString = new Field(&quot;name&quot;);

//使用重载方法
var fieldProperty = new Field(typeof(Project).GetProperty(nameof(Project.Name)));

//使用 lambda 表达式的方式
Expression&lt;Func&lt;Project, object&gt;&gt; expression = p =&gt; p.Name;
var fieldExpression = new Field(expression);
</code></pre>
<p>你也可以在实例化的时候设定 boost 值。</p>
<p>eg：当你使用如下构造函数时：</p>
<a id="more"></a>
<p></p><p class="code-caption" data-lang="csharp" data-line_number="backend" data-trim_indent="backend" data-label_position="outer" data-labels_left="Code" data-labels_right=":" data-labels_copy="Copy Code"><span class="code-caption-label"></span></p><p></p>
<pre><code class="csharp">public Field(string name, double? boost = null, string format = null)
</code></pre>
<ul>
<li>你可以设定一个提升值（boost），之后 Nest 会从设定的 Field 名称中获得对应的 boost 值。</li>
</ul>
<p></p><p class="code-caption" data-lang="csharp" data-line_number="backend" data-trim_indent="backend" data-label_position="outer" data-labels_left="Code" data-labels_right=":" data-labels_copy="Copy Code"><span class="code-caption-label"></span></p><p></p>
<pre><code class="csharp">var fieldString = &quot;name^2.1&quot;; //boost为 2.1
var field = new Field(fieldString);

//等效于
var field = new Field(&quot;name&quot;, 2.1);
</code></pre>
<h1 id="隐式转换"><a href="#隐式转换" class="headerlink" title="隐式转换"></a>隐式转换</h1><p>跟构造函数一样，你也可以直接将 string，PropertyInfo，lambda 表达式隐式转换为 Field 类，如下：</p>
<p></p><p class="code-caption" data-lang="csharp" data-line_number="backend" data-trim_indent="backend" data-label_position="outer" data-labels_left="Code" data-labels_right=":" data-labels_copy="Copy Code"><span class="code-caption-label"></span></p><p></p>
<pre><code class="csharp">Field fieldString = &quot;name&quot;;

Field fieldProperty = typeof(Project).GetProperty(nameof(Project.Name));

Expression&lt;Func&lt;Project, object&gt;&gt; expression = p =&gt; p.Name;
Field fieldExpression = expression;
</code></pre>
<h1 id="使用-Nest-Infer-方法"><a href="#使用-Nest-Infer-方法" class="headerlink" title="使用 Nest.Infer 方法"></a>使用 Nest.Infer 方法</h1><p>通过 Nest.Infer 可以简化从表达式创建 Field 实例：</p>
<p></p><p class="code-caption" data-lang="csharp" data-line_number="backend" data-trim_indent="backend" data-label_position="outer" data-labels_left="Code" data-labels_right=":" data-labels_copy="Copy Code"><span class="code-caption-label"></span></p><p></p>
<pre><code class="csharp">//使用 Nest.Infer 
var field = Nest.Infer.Field&lt;Project&gt;(p =&gt; p.Name);

//指定 boost
var field = Nest.Infer.Field&lt;Project&gt;(p =&gt; p.Name, 2.1);
</code></pre>
<h1 id="Field-名称的自动大小写转换"><a href="#Field-名称的自动大小写转换" class="headerlink" title="Field 名称的自动大小写转换"></a>Field 名称的自动大小写转换</h1><p>默认情况下，NEST 为了跟 JavaScript 和 JSON 统一，对 Field 使用 camelCase。</p>
<p>通过使用 ConnectionSettings 的 DefaultFieldNameInferrer() 方法，你可以修改默认行为，如下：</p>
<p></p><p class="code-caption" data-lang="csharp" data-line_number="backend" data-trim_indent="backend" data-label_position="outer" data-labels_left="Code" data-labels_right=":" data-labels_copy="Copy Code"><span class="code-caption-label"></span></p><p></p>
<pre><code class="csharp">var settings = new ConnectionSettings(new Uri(_esSettings.ServerUri))
        .DefaultFieldNameInferrer(dfni=&gt;dfni.ToUpper())
</code></pre>
<ul>
<li>将命名推断变更为了全部大写。</li>
</ul>
<p>但是，当使用下面的构造函数的时候，总是逐字匹配的（不会转换，传入什么样就是什么样）：</p>
<p></p><p class="code-caption" data-lang="csharp" data-line_number="backend" data-trim_indent="backend" data-label_position="outer" data-labels_left="Code" data-labels_right=":" data-labels_copy="Copy Code"><span class="code-caption-label"></span></p><p></p>
<pre><code class="csharp">public Field(string name, double? boost = null, string format = null)
</code></pre>
<p>如果您希望NEST完全不更改字段名称的大小写，只需将Func&lt;string，string&gt;传递给 DefaultFieldNameInferrer 即可，该函数仅返回输入字符串：</p>
<p></p><p class="code-caption" data-lang="csharp" data-line_number="backend" data-trim_indent="backend" data-label_position="outer" data-labels_left="Code" data-labels_right=":" data-labels_copy="Copy Code"><span class="code-caption-label"></span></p><p></p>
<pre><code class="csharp">var settings = new ConnectionSettings(new Uri(_esSettings.ServerUri))
        .DefaultFieldNameInferrer(p =&gt; p)
</code></pre>
<h1 id="使用表达式"><a href="#使用表达式" class="headerlink" title="使用表达式"></a>使用表达式</h1><blockquote>
<p>需要注意的是：表达式只支持成员变量。</p>
</blockquote>
<p>支持多级嵌套属性：</p>
<p></p><p class="code-caption" data-lang="csharp" data-line_number="backend" data-trim_indent="backend" data-label_position="outer" data-labels_left="Code" data-labels_right=":" data-labels_copy="Copy Code"><span class="code-caption-label"></span></p><p></p>
<pre><code class="csharp">Expect(&quot;leadDeveloper.firstName&quot;).WhenSerializing(Nest.Infer.Field&lt;Project&gt;(p =&gt; p.LeadDeveloper.FirstName));
</code></pre>
<p>处理集合索引器时，将忽略索引器访问权限，你可以遍历集合的属性：</p>
<p></p><p class="code-caption" data-lang="csharp" data-line_number="backend" data-trim_indent="backend" data-label_position="outer" data-labels_left="Code" data-labels_right=":" data-labels_copy="Copy Code"><span class="code-caption-label"></span></p><p></p>
<pre><code class="csharp">Expect(&quot;curatedTags&quot;).WhenSerializing(Nest.Infer.Field&lt;Project&gt;(p =&gt; p.CuratedTags[0]));
</code></pre>
<p>支持 Linq：</p>
<p></p><p class="code-caption" data-lang="csharp" data-line_number="backend" data-trim_indent="backend" data-label_position="outer" data-labels_left="Code" data-labels_right=":" data-labels_copy="Copy Code"><span class="code-caption-label"></span></p><p></p>
<pre><code class="csharp">Expect(&quot;curatedTags&quot;).WhenSerializing(Nest.Infer.Field&lt;Project&gt;(p =&gt; p.CuratedTags.First()));
Expect(&quot;curatedTags.added&quot;).WhenSerializing(Nest.Infer.Field&lt;Project&gt;(p =&gt; p.CuratedTags[0].Added));
Expect(&quot;curatedTags.name&quot;).WhenSerializing(Nest.Infer.Field&lt;Project&gt;(p =&gt; p.CuratedTags.First().Name));
</code></pre>
<p>字典：</p>
<ul>
<li>使用字典的时候，会自动级联转换如下：<br><p class="code-caption" data-lang="csharp" data-line_number="backend" data-trim_indent="backend" data-label_position="outer" data-labels_left="Code" data-labels_right=":" data-labels_copy="Copy Code"><span class="code-caption-label"></span></p><pre><code class="csharp">Expect(&quot;metadata.hardcoded&quot;).WhenSerializing(Nest.Infer.Field&lt;Project&gt;(p =&gt; p.Metadata[&quot;hardcoded&quot;]));
Expect(&quot;metadata.hardcoded.created&quot;).WhenSerializing(Nest.Infer.Field&lt;Project&gt;(p =&gt; p.Metadata[&quot;hardcoded&quot;].Created));
//对于 key，也会自动激烈使用
var variable = &quot;var&quot;;
Expect(&quot;metadata.var&quot;).WhenSerializing(Nest.Infer.Field&lt;Project&gt;(p =&gt; p.Metadata[variable]));
Expect(&quot;metadata.var.created&quot;).WhenSerializing(Nest.Infer.Field&lt;Project&gt;(p =&gt; p.Metadata[variable].Created));
</code></pre>
</li>
</ul>
<p>如果使用的是 Elasticearch 的多字段，这些“虚拟”子字段并不总是映射回你的 POCO 对象。通过在表达式上调用 .Suffix()，可以描述应映射的子字段及其映射方式：</p>
<p></p><p class="code-caption" data-lang="csharp" data-line_number="backend" data-trim_indent="backend" data-label_position="outer" data-labels_left="Code" data-labels_right=":" data-labels_copy="Copy Code"><span class="code-caption-label"></span></p><p></p>
<pre><code class="csharp">Expect(&quot;leadDeveloper.firstName.raw&quot;).WhenSerializing(
    Nest.Infer.Field&lt;Project&gt;(p =&gt; p.LeadDeveloper.FirstName.Suffix(&quot;raw&quot;)));

Expect(&quot;curatedTags.raw&quot;).WhenSerializing(
    Nest.Infer.Field&lt;Project&gt;(p =&gt; p.CuratedTags[0].Suffix(&quot;raw&quot;)));

Expect(&quot;curatedTags.raw&quot;).WhenSerializing(
    Nest.Infer.Field&lt;Project&gt;(p =&gt; p.CuratedTags.First().Suffix(&quot;raw&quot;)));

Expect(&quot;curatedTags.added.raw&quot;).WhenSerializing(
    Nest.Infer.Field&lt;Project&gt;(p =&gt; p.CuratedTags[0].Added.Suffix(&quot;raw&quot;)));

Expect(&quot;metadata.hardcoded.raw&quot;).WhenSerializing(
    Nest.Infer.Field&lt;Project&gt;(p =&gt; p.Metadata[&quot;hardcoded&quot;].Suffix(&quot;raw&quot;)));

Expect(&quot;metadata.hardcoded.created.raw&quot;).WhenSerializing(
    Nest.Infer.Field&lt;Project&gt;(p =&gt; p.Metadata[&quot;hardcoded&quot;].Created.Suffix(&quot;raw&quot;)));
</code></pre>
<p>你也可以直接链式使用 Suffix 方法</p>
<p></p><p class="code-caption" data-lang="csharp" data-line_number="backend" data-trim_indent="backend" data-label_position="outer" data-labels_left="Code" data-labels_right=":" data-labels_copy="Copy Code"><span class="code-caption-label"></span></p><p></p>
<pre><code class="csharp">Expect(&quot;curatedTags.name.raw.evendeeper&quot;).WhenSerializing(
    Nest.Infer.Field&lt;Project&gt;(p =&gt; p.CuratedTags.First().Name.Suffix(&quot;raw&quot;).Suffix(&quot;evendeeper&quot;)));
</code></pre>
<p>传递给 Suffix 方法的值也将会被正确估算：</p>
<p></p><p class="code-caption" data-lang="csharp" data-line_number="backend" data-trim_indent="backend" data-label_position="outer" data-labels_left="Code" data-labels_right=":" data-labels_copy="Copy Code"><span class="code-caption-label"></span></p><p></p>
<pre><code class="csharp">var variable = &quot;var&quot;;
var suffix = &quot;unanalyzed&quot;;
Expect(&quot;metadata.var.unanalyzed&quot;).WhenSerializing(
    Nest.Infer.Field&lt;Project&gt;(p =&gt; p.Metadata[variable].Suffix(suffix)));

Expect(&quot;metadata.var.created.unanalyzed&quot;).WhenSerializing(
    Nest.Infer.Field&lt;Project&gt;(p =&gt; p.Metadata[variable].Created.Suffix(suffix)));
</code></pre>
<p>也可以使用 .AppendSuffix() 方法将后缀“追加”到表达式中。在要将相同的后缀应用于字段列表的情况下，这很有用：</p>
<p></p><p class="code-caption" data-lang="csharp" data-line_number="backend" data-trim_indent="backend" data-label_position="outer" data-labels_left="Code" data-labels_right=":" data-labels_copy="Copy Code"><span class="code-caption-label"></span></p><p></p>
<pre><code class="csharp">var expressions = new List&lt;Expression&lt;Func&lt;Project, object&gt;&gt;&gt;
{
    p =&gt; p.Name,
    p =&gt; p.Description,
    p =&gt; p.CuratedTags.First().Name,
    p =&gt; p.LeadDeveloper.FirstName,
    p =&gt; p.Metadata[&quot;hardcoded&quot;]
};
</code></pre>
<p>在每个后面增加“raw后缀”：</p>
<p></p><p class="code-caption" data-lang="csharp" data-line_number="backend" data-trim_indent="backend" data-label_position="outer" data-labels_left="Code" data-labels_right=":" data-labels_copy="Copy Code"><span class="code-caption-label"></span></p><p></p>
<pre><code class="csharp">var fieldExpressions =
    expressions.Select&lt;Expression&lt;Func&lt;Project, object&gt;&gt;, Field&gt;(e =&gt; e.AppendSuffix(&quot;raw&quot;)).ToList();

Expect(&quot;name.raw&quot;).WhenSerializing(fieldExpressions[0]);
Expect(&quot;description.raw&quot;).WhenSerializing(fieldExpressions[1]);
Expect(&quot;curatedTags.name.raw&quot;).WhenSerializing(fieldExpressions[2]);
Expect(&quot;leadDeveloper.firstName.raw&quot;).WhenSerializing(fieldExpressions[3]);
Expect(&quot;metadata.hardcoded.raw&quot;).WhenSerializing(fieldExpressions[4]);
</code></pre>
<p>你也可以链式调用 .AppendSuffix()</p>
<p></p><p class="code-caption" data-lang="csharp" data-line_number="backend" data-trim_indent="backend" data-label_position="outer" data-labels_left="Code" data-labels_right=":" data-labels_copy="Copy Code"><span class="code-caption-label"></span></p><p></p>
<pre><code class="csharp">var multiSuffixFieldExpressions =
    expressions.Select&lt;Expression&lt;Func&lt;Project, object&gt;&gt;, Field&gt;(e =&gt; e.AppendSuffix(&quot;raw&quot;).AppendSuffix(&quot;evendeeper&quot;)).ToList();

Expect(&quot;name.raw.evendeeper&quot;).WhenSerializing(multiSuffixFieldExpressions[0]);
Expect(&quot;description.raw.evendeeper&quot;).WhenSerializing(multiSuffixFieldExpressions[1]);
Expect(&quot;curatedTags.name.raw.evendeeper&quot;).WhenSerializing(multiSuffixFieldExpressions[2]);
Expect(&quot;leadDeveloper.firstName.raw.evendeeper&quot;).WhenSerializing(multiSuffixFieldExpressions[3]);
Expect(&quot;metadata.hardcoded.raw.evendeeper&quot;).WhenSerializing(multiSuffixFieldExpressions[4]);
</code></pre>
<h1 id="使用特性"><a href="#使用特性" class="headerlink" title="使用特性"></a>使用特性</h1><p>使用 NEST 的属性特性可以让你指定一个新的名称来代替属性名。</p>
<p>使用 Text 特性：</p>
<p></p><p class="code-caption" data-lang="csharp" data-line_number="backend" data-trim_indent="backend" data-label_position="outer" data-labels_left="Code" data-labels_right=":" data-labels_copy="Copy Code"><span class="code-caption-label"></span></p><p></p>
<pre><code class="csharp">public class BuiltIn
{
    [Text(Name = &quot;naam&quot;)]
    public string Name { get; set; }
}

Expect(&quot;naam&quot;).WhenSerializing(Nest.Infer.Field&lt;BuiltIn&gt;(p =&gt; p.Name));
</code></pre>
<p>使用 DataMember 特性：</p>
<ul>
<li>如果一个属性使用了 DataMember 特性，那么你可以直接在该特性上进行指定。<br><p class="code-caption" data-lang="csharp" data-line_number="backend" data-trim_indent="backend" data-label_position="outer" data-labels_left="Code" data-labels_right=":" data-labels_copy="Copy Code"><span class="code-caption-label"></span></p><br><code>`</code> csharp<br>public class DataMember<br>{<br>  [DataMember(Name = “nameFromDataMember”)]<br>  public string Name { get; set; }<br>}</li>
</ul>
<p>Expect(“nameFromDataMember”).WhenSerializing(Nest.Infer.Field<datamember>(p =&gt; p.Name));</datamember></p>
<pre><code>
使用各序列化器的特性：
- NEST 支持使用特定的 JSON 库提供的序列化特性：如将 JsonNetSerializer 作为默认序列化，使用 JsonPropertyAttribute 来设定字段名

&lt;p class=&quot;code-caption&quot; data-lang=&quot;csharp&quot; data-line_number=&quot;backend&quot; data-trim_indent=&quot;backend&quot; data-label_position=&quot;outer&quot; data-labels_left=&quot;Code&quot; data-labels_right=&quot;:&quot; data-labels_copy=&quot;Copy Code&quot;&gt;&lt;span class=&quot;code-caption-label&quot;&gt;&lt;/span&gt;&lt;/p&gt;
``` csharp 
public class SerializerSpecific
{
    [PropertyName(&quot;nameInJson&quot;), JsonProperty(&quot;nameInJson&quot;)]
    public string Name { get; set; }
}

Expect(&quot;nameInJson&quot;).WhenSerializing(Nest.Infer.Field&lt;SerializerSpecific&gt;(p =&gt; p.Name));
</code></pre><p>如果在一个属性上同时指定了 Nest 提供的属性特性和序列化器提供的属性特性，Nest 特性优先级较高，如下：</p>
<p></p><p class="code-caption" data-lang="csharp" data-line_number="backend" data-trim_indent="backend" data-label_position="outer" data-labels_left="Code" data-labels_right=":" data-labels_copy="Copy Code"><span class="code-caption-label"></span></p><p></p>
<pre><code class="csharp">public class Both
{
    [Text(Name = &quot;naam&quot;)]
    [PropertyName(&quot;nameInJson&quot;), DataMember(Name = &quot;nameInJson&quot;)]
    public string Name { get; set; }
}

Expect(&quot;naam&quot;).WhenSerializing(Nest.Infer.Field&lt;Both&gt;(p =&gt; p.Name));
Expect(new
    {
        naam = &quot;Martijn Laarman&quot;
    }).WhenSerializing(new Both { Name = &quot;Martijn Laarman&quot; });
</code></pre>
<h1 id="字段推断缓存"><a href="#字段推断缓存" class="headerlink" title="字段推断缓存"></a>字段推断缓存</h1><p>每个 ConnectionSettings 实例都会缓存字段名称的解析：</p>
<ul>
<li>即不同的 ConnectionSettings 可以设定不同的推断规则。</li>
</ul>
<p>假设有如下演示类：</p>
<p></p><p class="code-caption" data-lang="csharp" data-line_number="backend" data-trim_indent="backend" data-label_position="outer" data-labels_left="Code" data-labels_right=":" data-labels_copy="Copy Code"><span class="code-caption-label"></span></p><p></p>
<pre><code class="csharp">class A { public C C { get; set; } }

class B { public C C { get; set; } }

class C
{
    public string Name { get; set; }
}
</code></pre>
<p>对于如下表达式代码：</p>
<p></p><p class="code-caption" data-lang="csharp" data-line_number="backend" data-trim_indent="backend" data-label_position="outer" data-labels_left="Code" data-labels_right=":" data-labels_copy="Copy Code"><span class="code-caption-label"></span></p><p></p>
<pre><code class="csharp">var fieldNameOnA = _client.Infer.Field(Nest.Infer.Field&lt;A&gt;(p =&gt; p.C.Name));
var fieldNameOnB = _client.Infer.Field(Nest.Infer.Field&lt;B&gt;(p =&gt; p.C.Name));
</code></pre>
<p>有：</p>
<ul>
<li>fieldNameOnA == “c.name”</li>
<li>fieldNameOnB == “c.name”</li>
</ul>
<p>现在创建一个新的 ConnectionSettings，重新映射 A.C 为 “d”：</p>
<p></p><p class="code-caption" data-lang="csharp" data-line_number="backend" data-trim_indent="backend" data-label_position="outer" data-labels_left="Code" data-labels_right=":" data-labels_copy="Copy Code"><span class="code-caption-label"></span></p><p></p>
<pre><code class="csharp">var newConnectionSettings = new TestConnectionSettings()
    .DefaultMappingFor&lt;A&gt;(m =&gt; m
        .PropertyName(p =&gt; p.C, &quot;d&quot;)
    );

var newClient = new ElasticClient(newConnectionSettings);

fieldNameOnA = newClient.Infer.Field(Nest.Infer.Field&lt;A&gt;(p =&gt; p.C.Name));
fieldNameOnB = newClient.Infer.Field(Nest.Infer.Field&lt;B&gt;(p =&gt; p.C.Name));

fieldNameOnA.Should().Be(&quot;d.name&quot;);  // 使用了默认映射规则
fieldNameOnB.Should().Be(&quot;c.name&quot;);
</code></pre>
<h1 id="推断字段名称的优先顺序"><a href="#推断字段名称的优先顺序" class="headerlink" title="推断字段名称的优先顺序"></a>推断字段名称的优先顺序</h1><p><strong>如上述，设定字段名称的方式如下：</strong></p>
<ul>
<li>在 ConnectionSettings上使用 .PropertyName 命名属性。</li>
<li>使用 Nest 的 PropertyNameAttribute。</li>
<li>使用序列化器提供的特性。</li>
<li>使用 DataMemberAttribute。</li>
<li>在 ConnectionSettings 上使用 DefaultFieldNameInferrer，默认情况下将使用骆驼命名属性。</li>
</ul>
<p>假设有以下测试用例：</p>
<p></p><p class="code-caption" data-lang="csharp" data-line_number="backend" data-trim_indent="backend" data-label_position="outer" data-labels_left="Code" data-labels_right=":" data-labels_copy="Copy Code"><span class="code-caption-label"></span></p><p></p>
<pre><code class="csharp">private class Precedence
{
    [Text(Name = &quot;renamedIgnoresNest&quot;)]    [PropertyName(&quot;renamedIgnoresJsonProperty&quot;),JsonProperty(&quot;renamedIgnoresJsonProperty&quot;)]
    public string RenamedOnConnectionSettings { get; set; }     //1

    [Text(Name = &quot;nestAtt&quot;)]
    [PropertyName(&quot;nestProp&quot;),JsonProperty(&quot;jsonProp&quot;)]
    public string NestAttribute { get; set; }                           //2

    [PropertyName(&quot;nestProp&quot;),JsonProperty(&quot;jsonProp&quot;)]
    public string NestProperty { get; set; }                            //3

    [DataMember(Name =&quot;jsonProp&quot;)]
    public string JsonProperty { get; set; }                            //4

    [DataMember(Name = &quot;data&quot;)]
    public string DataMember { get; set; }                          //5

}
</code></pre>
<p><strong>优先级如下：</strong></p>
<ol>
<li>即使此属性应用了各种属性，如果在 ConnectionSettings 上进行了设定，则 ConnectionSettings 上设置的优先级最高。</li>
<li>同时具有TextAttribute，PropertyNameAttribute 和 JsonPropertyAttribute：TextAttribute 优先级高。</li>
<li>同时具有 PropertyNameAttribute 和 JsonPropertyAttribute：PropertyNameAttribute 优先级高。</li>
<li>JsonPropertyAttribute 优先级高。</li>
<li>DataMemberAttribute 优先级高。</li>
</ol>
<p>自定义一个 IPropertyMappingProvider：将所有 AskSerializer 命名为 ask，并在 ConnectionSettings 中进行注册</p>
<p></p><p class="code-caption" data-lang="csharp" data-line_number="backend" data-trim_indent="backend" data-label_position="outer" data-labels_left="Code" data-labels_right=":" data-labels_copy="Copy Code"><span class="code-caption-label"></span></p><p></p>
<pre><code class="csharp">private class CustomPropertyMappingProvider : PropertyMappingProvider
{
    public override IPropertyMapping CreatePropertyMapping(MemberInfo memberInfo)
    {
        return memberInfo.Name == nameof(Precedence.AskSerializer)
            ? new PropertyMapping { Name = &quot;ask&quot; }
            : base.CreatePropertyMapping(memberInfo);
    }
}
</code></pre>
<p>在 ConnectionSettings 中注册</p>
<p></p><p class="code-caption" data-lang="csharp" data-line_number="backend" data-trim_indent="backend" data-label_position="outer" data-labels_left="Code" data-labels_right=":" data-labels_copy="Copy Code"><span class="code-caption-label"></span></p><p></p>
<pre><code class="csharp">var usingSettings = WithConnectionSettings(s =&gt; s

    .DefaultMappingFor&lt;Precedence&gt;(m =&gt; m
        .PropertyName(p =&gt; p.RenamedOnConnectionSettings, &quot;renamed&quot;) 
    )
    .DefaultFieldNameInferrer(p =&gt; p.ToUpperInvariant()) //如果没有其他规则适用或没有为给定字段指定字段，则为字段的默认推断
).WithPropertyMappingProvider(new CustomPropertyMappingProvider());  //使用自定义映射器

usingSettings.Expect(&quot;renamed&quot;).ForField(Nest.Infer.Field&lt;Precedence&gt;(p =&gt; p.RenamedOnConnectionSettings));
usingSettings.Expect(&quot;nestAtt&quot;).ForField(Nest.Infer.Field&lt;Precedence&gt;(p =&gt; p.NestAttribute));
usingSettings.Expect(&quot;nestProp&quot;).ForField(Nest.Infer.Field&lt;Precedence&gt;(p =&gt; p.NestProperty));
usingSettings.Expect(&quot;jsonProp&quot;).ForField(Nest.Infer.Field&lt;Precedence&gt;(p =&gt; p.JsonProperty));
usingSettings.Expect(&quot;ask&quot;).ForField(Nest.Infer.Field&lt;Precedence&gt;(p =&gt; p.AskSerializer));
usingSettings.Expect(&quot;data&quot;).ForField(Nest.Infer.Field&lt;Precedence&gt;(p =&gt; p.DataMember));
usingSettings.Expect(&quot;DEFAULTFIELDNAMEINFERRER&quot;).ForField(Nest.Infer.Field&lt;Precedence&gt;(p =&gt; p.DefaultFieldNameInferrer));
</code></pre>
<p>索引文档时也适用相同的命名规则</p>
<p></p><p class="code-caption" data-lang="csharp" data-line_number="backend" data-trim_indent="backend" data-label_position="outer" data-labels_left="Code" data-labels_right=":" data-labels_copy="Copy Code"><span class="code-caption-label"></span></p><p></p>
<pre><code class="csharp">usingSettings.Expect(new []
{
    &quot;ask&quot;,
    &quot;DEFAULTFIELDNAMEINFERRER&quot;,
    &quot;jsonProp&quot;,
    &quot;nestProp&quot;,
    &quot;nestAtt&quot;,
    &quot;renamed&quot;,
    &quot;data&quot;
}).AsPropertiesOf(new Precedence
{
    RenamedOnConnectionSettings = &quot;renamed on connection settings&quot;,
    NestAttribute = &quot;using a nest attribute&quot;,
    NestProperty = &quot;using a nest property&quot;,
    JsonProperty = &quot;the default serializer resolves json property attributes&quot;,
    AskSerializer = &quot;serializer fiddled with this one&quot;,
    DefaultFieldNameInferrer = &quot;shouting much?&quot;,
    DataMember = &quot;using a DataMember attribute&quot;
});
</code></pre>
<h1 id="覆盖继承的字段推断"><a href="#覆盖继承的字段推断" class="headerlink" title="覆盖继承的字段推断"></a>覆盖继承的字段推断</h1><p>从基本类型继承的属性可以忽略，并在 ConnectionSetting 上使用 DefaultMappingFor<t>。</t></p>
<p></p><p class="code-caption" data-lang="csharp" data-line_number="backend" data-trim_indent="backend" data-label_position="outer" data-labels_left="Code" data-labels_right=":" data-labels_copy="Copy Code"><span class="code-caption-label"></span></p><p></p>
<pre><code class="csharp">public class Parent
{
    public int Id { get; set; }
    public string Description { get; set; }
    public string IgnoreMe { get; set; }
}

public class Child : Parent { }

var usingSettings = WithConnectionSettings(s =&gt; s
        .DefaultMappingFor&lt;Child&gt;(m =&gt; m
            .PropertyName(p =&gt; p.Description, &quot;desc&quot;) //重命名 Description 为 desc
            .Ignore(p =&gt; p.IgnoreMe) //在 Child 类中忽略基类中的 IgnoreMe 属性
        )
    );
usingSettings.Expect(new []
    {
        &quot;id&quot;,
        &quot;desc&quot;,
    }).AsPropertiesOf(new Child
    {
        Id = 1,
        Description = &quot;this property will be renamed for Child&quot;,
        IgnoreMe = &quot;this property will be ignored (won&#39;t be serialized) for Child&quot;,
    });

public class SourceModel
{
    [PropertyName(&quot;gexo&quot;)]
    public GeoModel Geo { get; set; }
}

public class GeoModel
{
    [DataMember(Name = &quot;country_iso_code&quot;)]
    public string CountryIsoCode { get; set; }
}

var usingSettings = WithConnectionSettings(s =&gt; s)
        .WithSourceSerializer(JsonNetSerializer.Default);

usingSettings.Expect(&quot;gexo&quot;).ForField(Field&lt;SourceModel&gt;(p=&gt;p.Geo));
usingSettings.Expect(&quot;country_iso_code&quot;).ForField(Field&lt;GeoModel&gt;(p=&gt;p.CountryIsoCode));
usingSettings.Expect(new []
    {
        &quot;country_iso_code&quot;,
    }).AsPropertiesOf(new GeoModel { CountryIsoCode = &quot;nl&quot; });
usingSettings.Expect(new []
    {
        &quot;gexo&quot;,
    }).AsPropertiesOf(new SourceModel { Geo = new GeoModel { CountryIsoCode = &quot;nl&quot; } });

usingSettings.Expect(&quot;gexo.country_iso_code&quot;).ForField(Field&lt;SourceModel&gt;(p=&gt;p.Geo.CountryIsoCode));
</code></pre>

      

      <div>
        
        <div style="background-color: rgb(255, 23, 0);user-select: auto;height: 3px;width:100%;margin-top: 40px;margin-bottom:15px;"></div>

<!-- <p>常言道：学然后知不足，教然后知困。</p>
<p>我知道你的焦虑，一起共进加油：P</p>
<p>关不关注都无所谓，会根据生活节奏紧凑度定期分享些开发经验、搬砖生涯、痛点、感悟。</p>
<p>
        <img src="https://pic.zhuliang.ltd/20191213133908.gif" alt="欢迎关注我的订阅号：P" />
</p> -->
<ul class="post-copyright" style="margin-left:0px;">
    <li class="post-copyright-author">
        <strong>本文作者：</strong>积慕
    </li>
    <li class="post-copyright-link">
        <strong>本文链接：</strong>
        <a href="/2020/01/backend/Elasticsearch-Nest-field-inference.html" title="Elasticsearch.Nest 教程系列 9-4 转换：Field inference | 字段推断">https://blog.zhuliang.ltd/2020/01/backend/Elasticsearch-Nest-field-inference.html</a>
    </li>
    <li class="post-copyright-license">
        <strong>版权： </strong>
        本站文章均采用 <a href="http://creativecommons.org/licenses/by-nc-sa/3.0/cn/" rel="external nofollow"
            target="_blank">CC BY-NC-SA 3.0 CN</a> 许可协议，请勿用于商业，转载注明出处！
    </li>
</ul>
        
      </div>
    </div>

    <footer>
      
      
  
  <div class="categories">
    <a href="/categories/backend/">backend</a>
  </div>

      
  
  <div class="tags">
    <a href="/tags/教程/">教程</a>, <a href="/tags/Elasticsearch-Nest系列/">Elasticsearch.Nest系列</a>, <a href="/tags/Elasticsearch/">Elasticsearch</a>
  </div>

      <!-- 
  <div class="addthis addthis_toolbox addthis_default_style">
    
    
      <a class="addthis_button_tweet"></a>
    
    
      <a class="addthis_button_google_plusone" g:plusone:size="medium"></a>
    
    
      <a class="addthis_button_pinterest_pinit" pi:pinit:layout="horizontal"></a>
    
    <a class="addthis_counter addthis_pill_style"></a>
  </div>
  <script type="text/javascript" src="//s7.addthis.com/js/300/addthis_widget.js"></script>
 -->
      
      <div class="clearfix"></div>
    </footer>
  </div>
</article>

<!-- 
<section id="comment">
  <h1 class="title">留言</h1>

  <div id="vcomments" style="background-color: #fff"></div>
  <script>
    new Valine({
      el: '#vcomments',
      appId: 'aTPKmG6tjDo3CbIXzAPzrj4X-gzGzoHsz',
      appKey: 'hNgWFneNpEcMnBJclPQnDgsd',
      notify: true,
      verify: true, //验证码
      avatar: 'monsterid', //https://valine.js.org/avatar.html
      placeholder: '请输入你的评论'
    })
  </script>
</section>
 --> <!--启用/关闭 LeanCloud 评论--></div></div>
    <aside id="sidebar" class="alignright">
  
<div class="widget tag">
  <h3 class="title"><i class="iconfont icon-category"></i>&nbsp;&nbsp;分类</h3>
  <ul class="entry">
  
    <li><a href="/categories/Obsidian/">Obsidian</a><small>1</small></li>
  
    <li><a href="/categories/PowerUser/">PowerUser</a><small>4</small></li>
  
    <li><a href="/categories/backend/">backend</a><small>57</small></li>
  
    <li><a href="/categories/frontend/">frontend</a><small>9</small></li>
  
    <li><a href="/categories/operations/">operations</a><small>5</small></li>
  
    <li><a href="/categories/提前退休/">提前退休</a><small>2</small></li>
  
  </ul>
</div>


  
<div class="widget tag">
  <h3 class="title"><i class="iconfont icon-new3"></i>&nbsp;&nbsp;最新文章</h3>
  <ul class="entry">
    
      <li>
        <a href="/2024/11/PowerUser/install-docker-in-pve-lxc.html">1. 通过 PVE LXC 搭建 docker 环境</a>
      </li>
    
      <li>
        <a href="/2024/11/Obsidian/obsidian-render-pie-chart.html">2. 2 套用于 obsidian 的生成时间占用饼图脚本示例，基于 templater， charts，echarts+dataview</a>
      </li>
    
      <li>
        <a href="/2024/10/PowerUser/fix-ios18-samba-readonly-issue.html">3. 解决 ios 18（包括ipadOS 18） 下通过文件(files app)连接 samba 服务器，目录变成只读权限的问题</a>
      </li>
    
      <li>
        <a href="/2023/07/operations/how-to-use-pm2.html">4. PM2 的安装、配置和使用</a>
      </li>
    
      <li>
        <a href="/2023/07/backend/expose-intranet-netcoreapi-to-internet.html">5. 通过 DDNS+显性URL 把内网部署的.NET CORE WEBAPI 项目暴露到公网中</a>
      </li>
    
  </ul>
</div>


  
<div class="widget tag">
  <h3 class="title"><i class="iconfont icon-tag"></i>&nbsp;&nbsp;标签</h3>
  <ul class="entry">
  
    <li><a href="/tags/net-core/">.net core</a><small>12</small></li>
  
    <li><a href="/tags/Debian/">Debian</a><small>2</small></li>
  
    <li><a href="/tags/Docker/">Docker</a><small>1</small></li>
  
    <li><a href="/tags/Elasticsearch/">Elasticsearch</a><small>35</small></li>
  
    <li><a href="/tags/Elasticsearch-Nest系列/">Elasticsearch.Nest系列</a><small>35</small></li>
  
    <li><a href="/tags/Obsidian/">Obsidian</a><small>1</small></li>
  
    <li><a href="/tags/PVE/">PVE</a><small>2</small></li>
  
    <li><a href="/tags/StackExchange-Redis系列/">StackExchange.Redis系列</a><small>12</small></li>
  
    <li><a href="/tags/centos/">centos</a><small>3</small></li>
  
    <li><a href="/tags/flex/">flex</a><small>1</small></li>
  
    <li><a href="/tags/ios/">ios</a><small>1</small></li>
  
    <li><a href="/tags/javascript/">javascript</a><small>1</small></li>
  
    <li><a href="/tags/linux/">linux</a><small>4</small></li>
  
    <li><a href="/tags/nginx/">nginx</a><small>2</small></li>
  
    <li><a href="/tags/nuget/">nuget</a><small>2</small></li>
  
    <li><a href="/tags/react/">react</a><small>6</small></li>
  
    <li><a href="/tags/styled-components/">styled-components</a><small>1</small></li>
  
    <li><a href="/tags/内网穿透/">内网穿透</a><small>4</small></li>
  
    <li><a href="/tags/培训讲义/">培训讲义</a><small>2</small></li>
  
    <li><a href="/tags/基础知识/">基础知识</a><small>2</small></li>
  
    <li><a href="/tags/性能优化/">性能优化</a><small>2</small></li>
  
    <li><a href="/tags/教程/">教程</a><small>64</small></li>
  
    <li><a href="/tags/理财/">理财</a><small>2</small></li>
  
    <li><a href="/tags/生命周期/">生命周期</a><small>1</small></li>
  
    <li><a href="/tags/经验/">经验</a><small>4</small></li>
  
  </ul>
</div>


  
  <script type="text/javascript" charset="utf-8" src="/js/tagcloud.js"></script>
  <script type="text/javascript" charset="utf-8" src="/js/tagcanvas.js"></script>
  <div class="widget tag">
    <h3 class="title"><i class="iconfont icon-cloud1"></i>&nbsp;&nbsp;标签云</h3>
    <div id="myCanvasContainer" class="widget tagcloud">
      <canvas width="250" height="250" id="resCanvas" style="width:100%">
        <a href="/tags/net-core/" style="font-size: 17.14px;">.net core</a> <a href="/tags/Debian/" style="font-size: 11.43px;">Debian</a> <a href="/tags/Docker/" style="font-size: 10px;">Docker</a> <a href="/tags/Elasticsearch/" style="font-size: 18.57px;">Elasticsearch</a> <a href="/tags/Elasticsearch-Nest系列/" style="font-size: 18.57px;">Elasticsearch.Nest系列</a> <a href="/tags/Obsidian/" style="font-size: 10px;">Obsidian</a> <a href="/tags/PVE/" style="font-size: 11.43px;">PVE</a> <a href="/tags/StackExchange-Redis系列/" style="font-size: 17.14px;">StackExchange.Redis系列</a> <a href="/tags/centos/" style="font-size: 12.86px;">centos</a> <a href="/tags/flex/" style="font-size: 10px;">flex</a> <a href="/tags/ios/" style="font-size: 10px;">ios</a> <a href="/tags/javascript/" style="font-size: 10px;">javascript</a> <a href="/tags/linux/" style="font-size: 14.29px;">linux</a> <a href="/tags/nginx/" style="font-size: 11.43px;">nginx</a> <a href="/tags/nuget/" style="font-size: 11.43px;">nuget</a> <a href="/tags/react/" style="font-size: 15.71px;">react</a> <a href="/tags/styled-components/" style="font-size: 10px;">styled-components</a> <a href="/tags/内网穿透/" style="font-size: 14.29px;">内网穿透</a> <a href="/tags/培训讲义/" style="font-size: 11.43px;">培训讲义</a> <a href="/tags/基础知识/" style="font-size: 11.43px;">基础知识</a> <a href="/tags/性能优化/" style="font-size: 11.43px;">性能优化</a> <a href="/tags/教程/" style="font-size: 20px;">教程</a> <a href="/tags/理财/" style="font-size: 11.43px;">理财</a> <a href="/tags/生命周期/" style="font-size: 10px;">生命周期</a> <a href="/tags/经验/" style="font-size: 14.29px;">经验</a>
      </canvas>
    </div>
  </div>




</aside>
    <div class="clearfix"></div>
  </div>
  <footer id="footer" class="inner"><div class="alignleft">

  
  &copy; 2018 - 2024 &nbsp;<a href='/about'>积慕</a>
  
  &nbsp;&nbsp;<a href='https://www.cnblogs.com/deepthought/'>我的博客园地址</a>
  &nbsp;&nbsp;finalclassic#outlook.com
</div>

<div class="clearfix"></div>
<div>
  本站主题基于：<a href='https://github.com/hexojs/hexo-theme-light' rel="external nofollow">hexo-theme-light</a>
</div>
<div id="busuanzi_container_site_pv">
  本站总访问量&nbsp;<span id="busuanzi_value_site_pv"></span>&nbsp;次
</div>
<div style="width:300px;margin:0 auto; padding:20px 0;">
  <a target="_blank" href="http://www.beian.gov.cn/portal/registerSystemInfo?recordcode=31011702004805" style="display:inline-block;text-decoration:none;height:20px;line-height:20px;">
    <img src="https://pic.zhuliang.ltd/20200102164648.png" style="float:left;"><p style="float:left;height:20px;line-height:20px;margin: 0px 0px 0px 5px; color:#939393;">沪公网安备 31011702004805号</p></a>
</div></footer>
  <script src="/js/jquery-2.0.3.min.js"></script>
<script src="/js/jquery.imagesloaded.min.js"></script>
<script src="/js/gallery.js"></script>




<link rel="stylesheet" href="/fancybox/jquery.fancybox.css" media="screen" type="text/css">
<script src="/fancybox/jquery.fancybox.pack.js"></script>
<script type="text/javascript">
(function($){
  $('.fancybox').fancybox();
})(jQuery);
</script>


<script type="text/javascript">
hljs.initHighlightingOnLoad();
</script>

<!-- <script src="/js/busuanzi.pure.mini.js"></script> -->
<script async src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>
<script>
    var _hmt = _hmt || [];
    (function () {
        var hm = document.createElement("script");
        hm.src = "https://hm.baidu.com/hm.js?ea793b9c8d6b31df666a6bc15038e246";
        var s = document.getElementsByTagName("script")[0];
        s.parentNode.insertBefore(hm, s);
    })();
</script>
<script>
    (function () {
        var bp = document.createElement('script');
        var curProtocol = window.location.protocol.split(':')[0];
        if (curProtocol === 'https') {
            bp.src = 'https://zz.bdstatic.com/linksubmit/push.js';
        }
        else {
            bp.src = 'http://push.zhanzhang.baidu.com/push.js';
        }
        var s = document.getElementsByTagName("script")[0];
        s.parentNode.insertBefore(bp, s);
    })();
</script>
</body>
</html>
